﻿using System;
using System.Collections.Generic;
using System.Linq;
using TaskKernel.Domain;
using Xunit;

namespace TaskKernel.Tests
{
    public class DomainModelTest
    {
        [Fact]
        public void CreateTaskTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            var task = new Task(olegk, new Department(""), "taskname2");
            task.SetPriority(TaskPriority.Four);
            Assert.Equal(olegk, task.Owner);
            Assert.NotEqual(mihailk, task.Owner);
            Assert.Equal("taskname2", task.TaskName);
            Assert.Equal(TaskStatus.InProgress, task.Status);
            //Assert.Equal(TaskPriority.Four, task.Priority);
            Assert.Equal(1, task.Readers.Count());
        }

        [Fact]
        public Task ViewTaskTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            task.ViewTask(olegk);
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.False(task.IsReadBy(mihailk));
            Assert.Equal(1, task.Readers.Count());
            return task;
        }

        [Fact]
        public void DeleteParticipantTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            task.AddParticipants(olegk, new List<Account>
                                               {
                                                   mihailk
                                               }
               );
            int count = task.HistoryEntries.Count();
            task.DeleteParticipants(olegk, new List<Account>
                                               {
                                                   mihailk
                                               }
                );
            Assert.Equal(count + 1, task.HistoryEntries.Count());
            Assert.Equal(false, task.IsParticipant(mihailk));
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
        }

        [Fact]
        public void AddParticipantTest()
        {
            var olegk = new Account("olegk");
            var ilya = new Account("ilya");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            int count = task.HistoryEntries.Count();
            task.AddParticipants(olegk, new List<Account>
                                            {
                                                ilya
                                            }
                );
            Assert.Equal(count + 1, task.HistoryEntries.Count());
            Assert.Equal(true, task.IsParticipant(ilya));
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
        }

        [Fact]
        public void SetTagTest()
        {
            var olegk = new Account("olegk");
            var ilya = new Account("ilya");
            Task task = create_task(olegk, "SetTagTest");
            int count = task.HistoryEntries.Count();
            task.SetTag("blabla", olegk);
            Assert.Equal(count + 1, task.HistoryEntries.Count());
            Assert.Equal("blabla", task.Tag);
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
            count = task.HistoryEntries.Count();
            task.SetTag("blabla2", ilya);
            Assert.Equal(count + 1, task.HistoryEntries.Count());
            Assert.Equal("blabla2", task.Tag);
            Assert.Equal(true, task.IsReadBy(ilya));
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
            count = task.HistoryEntries.Count();
            task.SetTag("blabla2", ilya);
            Assert.Equal(count, task.HistoryEntries.Count());
            Assert.Equal("blabla2", task.Tag);
        }

        [Fact]
        public void AddCommentTest()
        {
            var olegk = new Account("olegk");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            int count = task.HistoryEntries.Count();
            task.AddHistoryEntry(olegk, "hell-o..uch :)");
            Assert.Equal(count + 1, task.HistoryEntries.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
        }

        [Fact]
        public void SetExecutorTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "SetExecutorTest");
            task.SetExecutor(mihailk, olegk);
            Assert.Equal(TaskStatus.InProgress, task.Status);
            Assert.Equal(mihailk, task.Executor);
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
        }

        [Fact]
        public void SetDepartmentTest()
        {
            var department = new Department("\\division");
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "SetDepartmentTest");
            task.SetExecutor(mihailk, olegk);
            task.SetPercentComplete(olegk, 37);
            Assert.Equal(mihailk, task.Executor);
            int count = task.HistoryEntries.Count();
            task.SetDepartment(olegk, department);
            count++;
            Assert.Equal(TaskStatus.InProgress, task.Status);
            Assert.Equal(37, task.PercentComplete);
            Assert.Null(task.Executor);
            Assert.False(task.HasExecutor());
            Assert.Equal(true, task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(count, task.HistoryEntries.Count());
        }

        [Fact]
        public void AddFileTest()
        {
            var olegk = new Account("olegk");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            int count = task.Files.Count();
            int i = task.HistoryEntries.Count();
            var file = new File( "test.txt",  new byte[0], 0 );
            task.AddFile(olegk,file);
            Assert.Equal(i + 1, task.HistoryEntries.Count());
            Assert.Equal(count + 1, task.Files.Count());
            Assert.Equal(TaskStatus.InProgress, task.Status);
            Assert.True(task.IsReadBy(olegk));
            Assert.Equal(1, task.Readers.Count());
        }

        [Fact]
        public void cClose_Task_By_Owner_Test()
        {
            var olegk = new Account("olegk");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            int i = task.HistoryEntries.Count();
            task.Close(olegk);
            Assert.True(task.IsClosed());
            Assert.Equal(olegk, task.ClosedBy);
            Assert.Equal(0, task.Readers.Count());
            Assert.Equal(i + 2, task.HistoryEntries.Count());
        }

        [Fact]
        public void RequestCloseFalseWhenTaskisClosedTest()
        {
            var olegk = new Account("olegk");
            Task task = create_task(olegk, "RequestCloseFalseWhenTaskisClosedTest");
            int i = task.HistoryEntries.Count();
            task.Close(olegk);
            Assert.True(task.IsClosed());
            Assert.False(task.RequestClose(olegk));
            Assert.Equal(olegk, task.ClosedBy);
            Assert.Equal(0, task.Readers.Count());
            Assert.Equal(i + 2, task.HistoryEntries.Count());
        }
        [Fact]
        public void Close_Task_By_Not_Owner_Test()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "Close_Task_By_Not_Owner_Test");
            int i = task.HistoryEntries.Count();
            task.RequestClose(mihailk);
            Assert.False(task.IsClosed());
            Assert.True(task.IsRequestClose());
            Assert.Equal(mihailk, task.AcceptClosedBy);
            Assert.Equal(1, task.Readers.Count());
            Assert.Equal(i + 2, task.HistoryEntries.Count());
        }

        [Fact]
        public void ForceClose_Task_By_Not_Owner_Test()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "Close_Task_By_Not_Owner_Test");
            int i = task.HistoryEntries.Count();
            task.ForceClose(mihailk);
            Assert.True(task.IsClosed());
            Assert.Equal(mihailk, task.ClosedBy);
            Assert.Equal(0, task.Readers.Count());
            Assert.Equal(i + 2, task.HistoryEntries.Count());
        }

        [Fact]
        public void DeleteReminderTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "delete reminder test");
            int count = task.Reminders.Count();
            Assert.False(task.DeleteReminder(mihailk));
            Assert.Equal(count, task.Reminders.Count());
            Assert.True(task.DeleteReminder(olegk));
            Assert.Equal(count - 1, task.Reminders.Count());
            Assert.False(task.DeleteReminder(olegk));
        }

        [Fact]
        public void StringToDateTimeTest()
        {
            DateTime? datetime = Tools.StringTodMyyyyHm("01/02/201015:34");
            Assert.NotNull(datetime);
            datetime = Tools.StringTodMyyyyHm("01/02/20105:3");
            Assert.NotNull(datetime);
        }

        [Fact]
        public void DifferenceCommentsTest()
        {
            var olegk = new Account("olegk");
            Task oldTask = create_task(olegk, "Close_Task_By_Owner_Test");
            Task task = create_task(olegk, "Close_Task_By_Owner_Test");
            task.AddHistoryEntry(olegk, "hell-o..uch :)");
            IEnumerable<AbstractTaskHistoryEntry> listComments = oldTask.GetDiffComments(task);
            Assert.True(listComments.Count() > 0);
        }

        [Fact]
        public void AddReminderTest()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            var plitka = new Account("plitka");
            Task task = create_task(olegk, "Add reminder test");
            int count = task.Reminders.Count();
            Assert.True(task.AddReminder(mihailk, new DateTime(1972, 11, 4), ""));
            Assert.False(task.AddReminder(mihailk, new DateTime(1972, 11, 4), ""));
            count++;
            Assert.Equal(count, task.Reminders.Count());
            Assert.True(task.AddReminder(plitka, new DateTime(1972, 11, 4), ""));
            Assert.False(task.AddReminder(plitka, new DateTime(1972, 11, 4), ""));
            count++;
            Assert.Equal(count, task.Reminders.Count());
        }

        [Fact]
        public void StartStopTriggerWorkingPeriodInTaskForAccount()
        {
            var olegk = new Account("olegk");
            var mihailk = new Account("mihailk");
            Task task = create_task(olegk, "StartStopTriggerWorkingPeriodInTaskForAccount");
            task.StartWorkingPeriodTrigger(olegk);
            task.StartWorkingPeriodTrigger(mihailk);
            Assert.Equal(2, task.WorkingPeriods.Count());
            Assert.True(task.HasPartialWorkingPeriodFor(olegk));
            Assert.True(task.HasPartialWorkingPeriodFor(mihailk));
            task.StartWorkingPeriodTrigger(olegk);
            Assert.Equal(2, task.WorkingPeriods.Count());
            Assert.False(task.HasPartialWorkingPeriodFor(olegk));
            Assert.True(task.HasPartialWorkingPeriodFor(mihailk));
            task.StartWorkingPeriodTrigger(mihailk);
            Assert.Equal(2, task.WorkingPeriods.Count());
            Assert.False(task.HasPartialWorkingPeriodFor(olegk));
            Assert.False(task.HasPartialWorkingPeriodFor(mihailk));
            task.StartWorkingPeriodTrigger(olegk);
            Assert.Equal(3, task.WorkingPeriods.Count());
            Assert.True(task.HasPartialWorkingPeriodFor(olegk));
            Assert.False(task.HasPartialWorkingPeriodFor(mihailk));
        }
        public Task create_task(Account account, string taskname)
        {
            var mihailk = new Account("mihailk");
            mihailk.SetMail("luck@servertd.spb.ru");
            var department = new Department("\\inform");
            department.SetMailBox("wefwefwef@wefwef.com");
            var task = new Task(account, department, taskname);
            task.SetStatus(TaskStatus.WaitingToClose);
            task.SetPriority(TaskPriority.Four);
            task.AddParticipant(account, mihailk);
            task.ViewTask(account);
            task.AddReminder(account, new DateTime(1972, 11, 4), "");
            return task;
        }
    }
}